﻿
Option Explicit On
'*******************************************************************
' Program: pkgVisio
' Author: Albert E Edlund
' Date:
'
' Purpose:
' Working with office object XML
'
'*******************************************************************


#Region " imports "

Imports System
Imports System.Object
Imports System.ComponentModel
Imports System.IO
Imports System.IO.TextReader
' need to reference windowsbase in .net
Imports System.IO.Packaging

' need for dbconnectionstringbuilder used in clsConnections
Imports System.Data.Common
Imports System.String
Imports System.Windows
Imports System.Windows.Forms
' working with image conversion
Imports System.Windows.Forms.AxHost

Imports System.Text.StringBuilder

Imports Microsoft.VisualBasic

Imports System.Text
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.ObjectModel

Imports System.Xml
Imports System.Linq
Imports System.Linq.Enumerable
Imports System.Windows.Input

Imports System.Xml.Serialization
Imports System.Xml.Linq
Imports System.Xml.XPath

Imports ADODB
Imports System.Data
Imports System.Data.OleDb
Imports System.Data.Sql




Imports Microsoft.Practices.EnterpriseLibrary.Common
Imports Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
Imports Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging


' visio v15 does not use a xName prefix which may put it into conflict with other open office apps
Imports <xmlns="http://schemas.microsoft.com/office/visio/2012/main">
Imports <xmlns:rs="urn:schemas-microsoft-com:rowset">

' generic namespace for office open xml, used in all of them
Imports <xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">

Imports pkgVisio.clsVisPackage
Imports pkgVisio.clsStructures


#End Region



'**********************************************************************************
'
' the masters file holds the attributes and elements for each of the master's, it
' also hold the resource id that points to the master file with their shape information
'
'**********************************************************************************
'
Public Class clsMasters



#Region " Properties and Definitions "



    '
    '
    '
    Private m_dictMastersID As Dictionary(Of Long, stcMasterData)
    Public Property dictMastersID As Dictionary(Of Long, stcMasterData)
        Get
            If m_dictMastersID Is Nothing Then
                m_dictMastersID = New Dictionary(Of Long, stcMasterData)
            End If
            dictMastersID = m_dictMastersID
        End Get
        Set(value As Dictionary(Of Long, stcMasterData))
            m_dictMastersID = value
        End Set
    End Property

    '
    '
    '
    Private m_dictMastersNameU As Dictionary(Of String, stcMasterData)
    Public Property dictMastersNameU As Dictionary(Of String, stcMasterData)
        Get
            If m_dictMastersNameU Is Nothing Then
                m_dictMastersNameU = New Dictionary(Of String, stcMasterData)
            End If
            dictMastersNameU = m_dictMastersNameU
        End Get
        Set(value As Dictionary(Of String, stcMasterData))
            m_dictMastersNameU = value
        End Set
    End Property

    '
    '
    '
    Public m_xDoc As XDocument
    Public Property xDoc As XDocument
        Get
            Return Me.m_xDoc
        End Get
        Set(value As XDocument)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "xDoc is Null.")
            End If
            Me.m_xDoc = value
        End Set
    End Property

    '
    ' This is the "master summary information" that is embedded in the "masters" file 
    '
    Public m_xDocMaster As XDocument
    Public Property xDocMaster As XDocument
        Get
            Return Me.m_xDocMaster
        End Get
        Set(value As XDocument)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "xDocMaster is Null.")
            End If
            Me.m_xDocMaster = value
        End Set
    End Property

    '
    '
    '
    Public m_visPackage As clsVisPackage
    Public Property visPackage As clsVisPackage
        Get
            visPackage = Me.m_visPackage
        End Get
        Set(value As clsVisPackage)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "visPackage is Null.")
            End If
            Me.m_visPackage = value
        End Set
    End Property

    '
    '
    '
    Private _relMasters As PackageRelationshipCollection
    Public Property relMasters As PackageRelationshipCollection
        Get
            relMasters = _relMasters
        End Get
        Set(value As PackageRelationshipCollection)
            _relMasters = value
        End Set
    End Property

    '
    '
    '
    Public Const MastersHeaderXML As String = "<?xml version=""1.0"" encoding=""utf-8"" ?>" _
    & "<Masters xml:space=""preserve"" " _
    & "xmlns=""http://schemas.microsoft.com/office/visio/2012/main"" " _
    & "xmlns:r=""http://schemas.openxmlformats.org/officeDocument/2006/relationships""> " _
    & "</Masters>"


#End Region


#Region " methods "

    '
    ' load the local xDoc with the Masters
    '
    Public Sub loadMastersXDoc(ByVal srcPackage As clsVisPackage)

        Me.visPackage = srcPackage
        _relMasters = Nothing
        Dim pkgpartMasters As PackagePart = Nothing


        Try


            Dim colPkgParts As Collection(Of pkgpartInfo) = New Collection(Of pkgpartInfo)
            colPkgParts = Me.visPackage.getPkgPartsByContent(pkgVisio.clsVisPackage.contXmlMasters)
            If colPkgParts.Count = 1 Then
                Me.m_xDoc = Nothing
                If (colPkgParts(0).pkgpartType = pkgpartTypeEnum.Part) And _
                        (colPkgParts(0).pkgpartPath.Contains(".xml")) Then
                    Using CurrentPackage As Package = Package.Open(Me.visPackage.fileCurrent, FileMode.Open, FileAccess.Read)
                        pkgpartMasters = CurrentPackage.GetPart(New Uri(colPkgParts(0).pkgpartPath, UriKind.Relative))
                        '  Load the document XML in the part into an XDocument instance.
                        Me.xDoc = XDocument.Load(XmlReader.Create(pkgpartMasters.GetStream()))
                        'relMasters = pkgpartMasters.GetRelationships
                        'Dim intRelCt As Integer = relMasters.Count

                        CurrentPackage.Close()

                    End Using
                End If ' test for xml part

            End If ' test for part found

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub

    '
    ' get the unique information for the master from the masters element
    '
    Public Sub loadMasterSummaryByMasterID(ByVal masterID As String)
        Try

            Me.m_xDocMaster = Nothing

            Dim qryMaster = From mstrSel In Me.xDoc...<Master>
                    Where mstrSel.@ID = masterID

            If qryMaster.Count = 1 Then
                Using stringReader As New StringReader(qryMaster.First.ToString)
                    Me.xDocMaster = XDocument.Load(XmlReader.Create(stringReader))
                End Using
            End If ' test for query found

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
    End Sub


    '
    ' get the unique information for the master from the masters element
    '
    Public Sub loadMasterSummaryByNameU(ByVal masterNameU As String)
        Try

            Me.m_xDocMaster = Nothing

            'Dim qryMaster = From mstrSel In Me.xDoc...<Master>
            'Where(LCase(mstrSel.@NameU) = LCase(masterNameU))

            Dim newXNamespace As XNamespace = getNameSpaceFromPrefix(Me.xDoc, "")
            Dim qryMaster = From mstrSel In Me.xDoc.Descendants(newXNamespace + "Master")
                Where (LCase(mstrSel.@NameU) = LCase(masterNameU))


            If qryMaster.Count = 1 Then
                Using stringReader As New StringReader(qryMaster.First.ToString)
                    Me.xDocMaster = XDocument.Load(XmlReader.Create(stringReader))
                End Using
            Else
                'MsgBox("qryMaster.Count <> 1 for Master.NameU " & masterNameU)
            End If ' test for query found

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
    End Sub

    '
    ' load a list of masters names and ids into a list control
    ' and create the master_info dictionary
    '
    Public Sub loadMasters _
        (ByRef lvControl As ListView)


        Dim lngMstId As Long = -1
        Dim strMstName As String = ""
        Dim strMstNameU As String = ""
        Dim strMstRid As String = ""
        Dim strMstFile As String = ""
        Dim tempDoc As XDocument = Nothing
        Dim imgIcon As System.Drawing.Image = Nothing
        Dim mstrsImgList As ImageList = New ImageList


        m_dictMastersID = Nothing
        m_dictMastersID = New Dictionary(Of Long, stcMasterData)
        m_dictMastersNameU = Nothing
        m_dictMastersNameU = New Dictionary(Of String, stcMasterData)

        Try

            Dim qryMaster = Me.xDoc...<Master>
            Dim intMasters As Integer = qryMaster.Count
            Dim docMaster As XDocument = Nothing

            If lvControl IsNot Nothing Then
                lvControl.Items.Clear()
                lvControl.Columns.Clear()
                lvControl.View = View.Details
                lvControl.AllowColumnReorder = True
                lvControl.FullRowSelect = True
                lvControl.Columns.Add("Id", 50, HorizontalAlignment.Right)
                'lvControl.Columns.Add("Name", 150, HorizontalAlignment.Left)
                lvControl.Columns.Add("NameU", 150, HorizontalAlignment.Left)
                lvControl.Columns.Add("RelId", 50, HorizontalAlignment.Left)
                lvControl.Columns.Add("File", 200, HorizontalAlignment.Left)

                lvControl.LargeImageList = mstrsImgList
                lvControl.SmallImageList = mstrsImgList

            End If

            ' get the pagesheet information from the pages file
            For Each master In qryMaster

                Dim lvItem As ListViewItem

                lngMstId = -1
                strMstName = "NoMstName"
                strMstNameU = "NoMstNameU"
                strMstRid = "NoRelId"
                strMstFile = "NoFile"

                Dim listOfAttributes As IEnumerable(Of XAttribute) = _
                    From att In master.Attributes() _
                    Select att
                For Each att As XAttribute In listOfAttributes
                    ' Console.WriteLine("{0}={1}", att.Name.LocalName, att.Value)
                    Select Case LCase(att.Name.LocalName)
                        Case "id"
                            lngMstId = CLng(att.Value)
                        Case "name"
                            ' get the recordset name
                            strMstName = CStr(att.Value)
                        Case "nameu"
                            strMstNameU = CStr(att.Value)
                    End Select
                Next att

                ' get the relationship id
                Dim listofElements As IEnumerable(Of XElement) = _
                    From elem In master.Elements() _
                    Select elem
                For Each elem As XElement In listofElements
                    Select Case LCase(elem.Name.LocalName)
                        Case "rel"
                            strMstRid = CStr(elem.@r:id)
                        Case "pagesheet"
                        Case "icon"
                            Using stringReader As New StringReader(elem.ToString)
                                tempDoc = XDocument.Load(XmlReader.Create(stringReader))
                                mstrsImgList.Images.Add(CStr(lngMstId), convertIcon(tempDoc))
                            End Using
                    End Select
                Next elem

                ' go find the associated file
                For Each PkgPart In Me.visPackage.colPkgPartInfo
                    If PkgPart.pkgpartContentType = clsVisPackage.contXmlMaster _
                        And PkgPart.pkgpartParent = "/visio/masters/masters.xml" _
                        And PkgPart.pkgpartResourceId = strMstRid Then
                        strMstFile = PkgPart.pkgpartPath
                        Exit For
                    End If
                Next PkgPart


                Dim newMaster As stcMasterData = New stcMasterData
                newMaster.mstId = lngMstId
                newMaster.mstName = strMstName
                newMaster.mstNameU = strMstNameU
                newMaster.mstResource = strMstRid
                newMaster.mstFile = strMstFile
                newMaster.mstShpObjType = getShapeObjType(strMstFile)
                dictMastersID.Add(lngMstId, newMaster)
                dictMastersNameU.Add(strMstNameU, newMaster)

                If lvControl IsNot Nothing Then
                    lvItem = New ListViewItem(lngMstId)
                    'lvItem.SubItems.Add(strMstName)
                    lvItem.SubItems.Add(strMstNameU)
                    lvItem.SubItems.Add(strMstRid)
                    lvItem.SubItems.Add(strMstFile)

                    lvItem.ImageKey = CStr(lngMstId)
                    lvControl.Items.Add(lvItem)
                End If ' test for control

            Next master

            'Debug.Print(dictMastersID.Count)

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub

    '
    ' pass in an xdocument, find the icon element, return an image
    '
    Public Function convertIcon(ByVal tempDoc As XDocument) _
                As System.Drawing.Image

        Dim imgReturn As System.Drawing.Image = Nothing
        Dim rdrXML As XmlTextReader = Nothing

        Try



            rdrXML = New XmlTextReader(New StringReader(tempDoc.ToString))
            rdrXML.WhitespaceHandling = WhitespaceHandling.None

            Dim myMaster As Object = rdrXML.NameTable.Add("Master")
            Dim myIcon As Object = rdrXML.NameTable.Add("Icon")

            While rdrXML.Read
                If myIcon = rdrXML.LocalName AndAlso rdrXML.NodeType = XmlNodeType.Element Then

                    Dim arrByte As Byte() = New Byte(4999) {}
                    Dim intLen As Integer = rdrXML.ReadBase64(arrByte, 0, 5000)

                    Dim streamMem As New System.IO.MemoryStream
                    streamMem.Write(arrByte, 0, intLen)
                    streamMem.Position = 0

                    ' build the image return from an icon
                    ' Dim iconReturn As System.Drawing.Icon
                    ' iconReturn = New Icon(streamMem)
                    ' imgReturn = iconReturn.ToBitmap

                    ' build the image return directly
                    imgReturn = System.Drawing.Image.FromStream(streamMem, True)
                    Dim testFile As String = "c:\temp\temp.bmp"
                    Try
                        'imgReturn.Save(testFile, System.Drawing.Imaging.ImageFormat.Bmp)
                    Catch
                    End Try
                    Exit While
                End If
            End While

        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        If rdrXML IsNot Nothing Then
            rdrXML = Nothing
        End If

        convertIcon = imgReturn

    End Function

    '
    ' pass in the file name for the master shape object contents and get the object type
    ' information so that we don't have to search for it again
    '
    Public Function getShapeObjType(ByVal strMstrFile As String) As stcFlagObjType

        Dim intReturn As stcFlagObjType
        Dim visMaster As clsMaster = New clsMaster
        Dim objFlag As stcFlagObjType = New stcFlagObjType

        Try

            visMaster.visPackage = Me.visPackage
            'get the master shape data and load it 
            visMaster.loadMasterShapeXDoc(strMstrFile)

            visMaster.visPackage.readAttAndElem(visMaster.xDoc, "", "Shape")
            ' when the elemDict was built the cell name was concatenated with "cell_" to keep keys unique
            Dim strValue As String = "0"
            Try
                strValue = visMaster.visPackage.elemDict("cell_ObjType").ToString
                ' when the elemDict was built, cell elements are saved as either cellV for value, or cellF for formula
            Catch
            End Try
            strValue = strValue.Replace("cellV = ", "")

            ' test to see if the shape is 1D
            objFlag.ulngMask = CLng(strValue)
            Dim bln1D As Boolean = objFlag.IsEqual(stcFlagObjType.Flag.visLOFlagsRoutable)

            intReturn = objFlag

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        visMaster = Nothing

        'objFlag = Nothing

        getShapeObjType = intReturn

    End Function

    '
    '
    '
    Public Function existsMasterNameU(ByVal strNameU As String) As Boolean

        Dim blnReturn As Boolean = False

        Dim qryMaster = From mstrSel In Me.xDoc...<Master>
                Where LCase(mstrSel.@NameU) = LCase(strNameU)

        If qryMaster.Count = 1 Then
            blnReturn = True
        End If ' test for query found

        Return blnReturn

    End Function

    '
    ' get the current maxMasterId number
    '
    Public Function maxMasterId() As Long
        maxMasterId = Me.dictMastersID.Keys.Max
    End Function

    '
    ' get the current max relationship id (rId number)
    '
    Public Function maxRelId() As Integer
        Dim intReturn As Integer = -1
        Dim strRel As String
        Dim arrList As ArrayList = New ArrayList
        Dim master As stcMasterData
        For Each master In dictMastersID.Values
            strRel = master.mstResource
            If strRel.StartsWith("rId") Then
                arrList.Add(CInt(strRel.Substring(3)))
            End If
        Next master
        arrList.Sort()
        intReturn = arrList(arrList.Count - 1)
        Return intReturn
    End Function


#End Region

#Region " add master/masters "


    '
    ' as part of the demo package we load three masters into the package
    ' we expect at least one of them to be a dynamic connector
    '
    Public Sub addTestMasterObjectsToPackage _
        (ByVal strPackagePath As String, _
         ByVal strStencilPath As String, _
         ByVal strMasterNames() As String)

        If strStencilPath = "" Then
            strStencilPath = clsWindows.strTestStencil
        End If
        If strMasterNames.Count = 0 Then
            strMasterNames = {"Certificate server", "Router", "Dynamic connector"}
        End If



        Dim xdocMasterSummary As XDocument = Nothing
        Dim xdocMasterContents As XDocument = Nothing
        Dim xelemFirstShape As XElement = Nothing
        Dim visShape As clsShape = Nothing
        Dim visCell As stcCell = New stcCell

        Try

            Dim intX As Integer = -1
            Dim intMasterCt As Integer = strMasterNames.Count
            Dim strMasterFile As String = ""
            Dim strMasterNameU As String = ""
            Dim strId As String = ""
            Dim strRid As String = ""
            For intX = 0 To intMasterCt - 1
                strMasterFile = "master" & CStr(intX + 1) & ".xml"
                strId = CStr(intX)
                strRid = "rId" & CStr(intX + 1)
                strMasterNameU = strMasterNames(intX)
                addTestMasterObjectToPackage(strPackagePath, strStencilPath, strMasterNameU, strId, strRid, strMasterFile)
            Next intX

            GC.Collect()
            GC.Collect()


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        If xdocMasterContents IsNot Nothing Then
            xdocMasterContents = Nothing
        End If

        If xdocMasterSummary IsNot Nothing Then
            xdocMasterSummary = Nothing
        End If
        GC.Collect()


    End Sub

    '
    ' for the test masters we modify the sizes
    '
    Private Sub addTestMasterObjectToPackage _
        (ByVal strPackagePath As String, _
         ByVal strStencilPath As String, _
         ByVal strMasterNameU As String, _
         ByVal strId As String, _
         ByVal strRid As String, _
         ByVal strMasterFile As String)


        Try

            Dim strNS As String = "xmlns=""http://schemas.microsoft.com/office/visio/2012/main"""

            Dim xdocMasterSummary As XDocument = Nothing
            Dim xdocMasterContents As XDocument = Nothing
            Dim xdocTemp As XDocument = Nothing

            Dim visShape As clsShape = Nothing
            Dim visPageSheet As clsShape = Nothing
            Dim visCell As stcCell = New stcCell

            Dim xelemMasterShapes As XElement = Nothing
            Dim xelemMasterPageSheet As XElement = Nothing

            ' get the server master
            Using package As Package = package.Open(strPackagePath, FileMode.Open, FileAccess.ReadWrite)

                xdocMasterSummary = Nothing
                xdocMasterContents = Nothing

                readMasterFromStencil _
                    (strStencilPath, _
                     strMasterNameU, _
                     xdocMasterSummary, _
                     xdocMasterContents)

                If xdocMasterSummary IsNot Nothing _
                    And xdocMasterContents IsNot Nothing Then


                    If LCase(strMasterNameU) <> "dynamic connector" Then

                        '
                        ' first work through changing the master shape
                        '
                        Dim qryMasterContents = xdocMasterContents...<MasterContents>
                        Dim listOfMasterElements As IEnumerable(Of XElement) = _
                            From elem In qryMasterContents.Elements() _
                            Select elem
                        For Each elem As XElement In listOfMasterElements
                            Dim strElemName As String = LCase(elem.Name.LocalName)
                            Select Case strElemName
                                Case "shapes"
                                    xelemMasterShapes = elem
                                    Exit For
                            End Select
                        Next elem

                        ' setup to resize the primary shape 
                        Dim xelemNewShape As XElement = xelemMasterShapes.Descendants.First
                        If xdocTemp IsNot Nothing Then
                            xdocTemp = Nothing
                        End If
                        xdocTemp = New XDocument
                        xdocTemp.Add(xelemNewShape)
                        ' add a set of standard connection points to the master contents
                        If visShape IsNot Nothing Then
                            visShape = Nothing
                        End If
                        visShape = New clsShape
                        visShape.visPackage = Me.visPackage
                        visShape.xDoc = New XDocument
                        visShape.xDoc = xdocTemp

                        visCell.Reset()
                        visCell.cellName = "Height"
                        visCell.cellValue = "0.5"
                        visCell.cellUnits = "IN"
                        visShape.setShapeCell("Height", visCell, "<?NewValue V?>")

                        visCell.Reset()
                        visCell.cellName = "Width"
                        visCell.cellValue = "0.5"
                        visCell.cellUnits = "IN"
                        visShape.setShapeCell("Width", visCell, "<?NewValue V?>")

                        visCell.Reset()
                        visCell.cellName = "PinX"
                        visCell.cellValue = "0.25"
                        visCell.cellUnits = "IN"
                        visShape.setShapeCell("PinX", visCell, "<?NewValue V?>")
                        visCell.Reset()
                        visCell.cellName = "PinY"
                        visCell.cellValue = "0.25"
                        visCell.cellUnits = "IN"
                        visShape.setShapeCell("PinY", visCell, "<?NewValue V?>")

                        visCell.Reset()
                        visCell.cellName = "LocPinX"
                        visCell.cellValue = "0.25"
                        visCell.cellUnits = "IN"
                        visShape.setShapeCell("LocPinX", visCell, "<?NewValue V?>")
                        visCell.Reset()
                        visCell.cellName = "LocPinY"
                        visCell.cellValue = "0.25"
                        visCell.cellUnits = "IN"
                        visShape.setShapeCell("LocPinY", visCell, "<?NewValue V?>")


                        Dim qrylclMasterRootShape = visShape.xDoc...<Shape>
                        Dim intShapeCt As Integer = qrylclMasterRootShape.Count
                        Dim intX As Integer = -1
                        If 0 < intShapeCt Then
                            For intX = 1 To intShapeCt - 1
                                Dim xelemTemp As XElement = qrylclMasterRootShape.ElementAt(intX)
                                xelemTemp.Attributes("LineStyle").Remove()
                                xelemTemp.Attributes("FillStyle").Remove()
                                xelemTemp.Attributes("TextStyle").Remove()
                            Next intX
                        End If


                        Dim xelemMasterShape As XElement = visShape.xDoc.Descendants.FirstOrDefault
                        Dim strNewShape As String = xelemMasterShape.ToString
                        Dim intStart As Integer = strNewShape.Length
                        strNewShape = strNewShape.Replace(strNS, "")
                        Dim intEnd As Integer = strNewShape.Length
                        ' Debug.Print(strMaster1NameU & " " & CStr(intStart) & " " & CStr(intEnd))
                        xelemMasterShape = XElement.Load((XmlReader.Create(New StringReader(strNewShape))))

                        xelemNewShape.ReplaceWith(xelemMasterShape)


                        'If blnAddStandardConnPts = True Then
                        '    visShape.initDictConnPtsFields()
                        '    visShape.AddStandardConnections()
                        'End If

                        '
                        ' now resize the pagesheet associated with the primary shape
                        '
                        Dim qryMasterSummary = xdocMasterSummary...<Master>
                        Dim listOfMasterSummaryElements As IEnumerable(Of XElement) = _
                            From elem In qryMasterSummary.Elements() _
                            Select elem
                        For Each elem As XElement In listOfMasterSummaryElements
                            Dim strElemName As String = LCase(elem.Name.LocalName)
                            Select Case strElemName
                                Case "pagesheet"
                                    xelemMasterPageSheet = elem
                                    Exit For
                            End Select
                        Next elem

                        ' setup resize the pagesheet
                        Dim xelemNewPageSheet As XElement = xelemMasterPageSheet
                        If xdocTemp IsNot Nothing Then
                            xdocTemp = Nothing
                        End If
                        xdocTemp = New XDocument
                        xdocTemp.Add(xelemMasterPageSheet)
                        ' add a set of standard connection points to the master contents
                        If visPageSheet IsNot Nothing Then
                            visPageSheet = Nothing
                        End If
                        visPageSheet = New clsShape
                        visPageSheet.visPackage = Me.visPackage
                        visPageSheet.xDoc = New XDocument
                        visPageSheet.xDoc = xdocTemp

                        visCell.Reset()
                        visCell.cellName = "PageWidth"
                        visCell.cellValue = "0.5"
                        visCell.cellUnits = "IN"
                        visPageSheet.setShapeCell("PageWidth", visCell, "<?NewValue V?>")
                        visCell.Reset()
                        visCell.cellName = "PageHeight"
                        visCell.cellValue = "0.5"
                        visCell.cellUnits = "IN"
                        visPageSheet.setShapeCell("PageHeight", visCell, "<?NewValue V?>")


                        Dim xelemMasterPage As XElement = visPageSheet.xDoc.Descendants.FirstOrDefault
                        strNewShape = xelemMasterPage.ToString
                        intStart = strNewShape.Length
                        strNewShape = strNewShape.Replace(strNS, "")
                        intEnd = strNewShape.Length
                        xelemMasterPage = XElement.Load((XmlReader.Create(New StringReader(strNewShape))))

                        xelemNewPageSheet.ReplaceWith(xelemMasterPage)


                    Else

                        Dim qryMasterContents = xdocMasterContents...<MasterContents>
                        Dim listOfMasterElements As IEnumerable(Of XElement) = _
                            From elem In qryMasterContents.Elements() _
                            Select elem
                        For Each elem As XElement In listOfMasterElements
                            Dim strElemName As String = LCase(elem.Name.LocalName)
                            Select Case strElemName
                                Case "shapes"
                                    xelemMasterShapes = elem
                                    Exit For
                            End Select
                        Next elem

                        ' setup to resize the primary shape 
                        Dim xelemNewShape As XElement = xelemMasterShapes.Descendants.First
                        If xdocTemp IsNot Nothing Then
                            xdocTemp = Nothing
                        End If
                        xdocTemp = New XDocument
                        xdocTemp.Add(xelemNewShape)
                        ' add a set of standard connection points to the master contents
                        If visShape IsNot Nothing Then
                            visShape = Nothing
                        End If
                        visShape = New clsShape
                        visShape.visPackage = Me.visPackage
                        visShape.xDoc = New XDocument
                        visShape.xDoc = xdocTemp

                        Dim qrylclMasterRootShape = visShape.xDoc...<Shape>
                        Dim intShapeCt As Integer = qrylclMasterRootShape.Count
                        Dim intX As Integer = -1
                        If intShapeCt = 1 Then

                            Dim xelemTemp As XElement = qrylclMasterRootShape.ElementAt(0)
                            xelemTemp.SetAttributeValue("LineStyle", "3")
                            xelemTemp.SetAttributeValue("FillStyle", "3")
                            xelemTemp.SetAttributeValue("TextStyle", "3")

                        End If


                        Dim xelemMasterShape As XElement = visShape.xDoc.Descendants.FirstOrDefault
                        Dim strNewShape As String = xelemMasterShape.ToString
                        Dim intStart As Integer = strNewShape.Length
                        strNewShape = strNewShape.Replace(strNS, "")
                        Dim intEnd As Integer = strNewShape.Length
                        ' Debug.Print(strMaster1NameU & " " & CStr(intStart) & " " & CStr(intEnd))
                        xelemMasterShape = XElement.Load((XmlReader.Create(New StringReader(strNewShape))))

                        xelemNewShape.ReplaceWith(xelemMasterShape)

                    End If ' test for other than dynamic connector

                    addMasterToMastersPkgPart _
                        (package, xdocMasterSummary, xdocMasterContents, strId, strMasterFile, strRid)


                End If

                package.Flush()
                package.Close()

            End Using

            visShape = Nothing
            visPageSheet = Nothing

            xdocMasterSummary = Nothing
            xdocMasterContents = Nothing

            GC.Collect()

        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub


    '
    ' just adds a blank masters packagepart to the current package
    '
    Public Sub addMastersToPkg _
        (ByRef packageCurrent As Package, _
         ByVal strRid As String)

        Try

            '**********************************************
            ' Add the Masters part to the Package
            '**********************************************
            ' Relative path and filename of the core file to add to the package.
            Dim mastersPath As String = "/visio/masters/masters.xml"
            Dim partUriMasters As Uri = PackUriHelper.CreatePartUri(New Uri(mastersPath, UriKind.Relative))
            Dim packagePartMasters As PackagePart = packageCurrent.CreatePart(partUriMasters, clsVisPackage.contXmlMasters)

            packageCurrent.CreateRelationship(packagePartMasters.Uri, TargetMode.Internal, clsVisPackage.relRidMasters, strRid)


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
    End Sub

    '
    ' add the master contents as a file to the masters directory path
    '
    Public Sub addMasterToMastersPkgPart _
        (ByRef packageCurrent As Package, _
         ByVal xdocMasterSummary As XDocument, _
         ByVal xdocMasterContents As XDocument, _
         ByVal strNewId As String, _
         Optional ByVal strNewMasterPath As String = "master1.xml", _
         Optional ByVal strNewRid As String = "rId1")

        Try

            Const bufSize As Integer = &H1000
            Dim uniEncoding As New UTF8Encoding
            Dim byteXML As Byte()


            ' go get the masters package part
            Me.m_xDoc = Nothing
            Dim pkgpartMasters As PackagePart = Nothing
            Dim mastersPath As String = "/visio/masters/masters.xml"
            pkgpartMasters = packageCurrent.GetPart(New Uri(mastersPath, UriKind.Relative))
            If pkgpartMasters IsNot Nothing Then
                '  Load the document XML in the part into an XDocument instance.
                Me.xDoc = XDocument.Load(XmlReader.Create(pkgpartMasters.GetStream()))
            Else
                Exit Sub
            End If ' test for part found

            ' get the xml summary from the xDocument as an xElement
            Dim xelemMasters As XElement = Me.xDoc.Elements.FirstOrDefault

            Dim xelemNewMaster As XElement = Nothing
            If xdocMasterSummary Is Nothing Then
                xelemNewMaster = XElement.Load((XmlReader.Create(New StringReader(clsMaster.MasterTemplateXml))))
            Else
                xelemNewMaster = xdocMasterSummary.Elements.FirstOrDefault
            End If
            ' change the id
            xelemNewMaster.SetAttributeValue("ID", strNewId)

            ' get the relationship id
            Dim listofElements As IEnumerable(Of XElement) = _
                From elem In xelemNewMaster.Elements() _
                Select elem
            For Each elem As XElement In listofElements
                Select Case LCase(elem.Name.LocalName)
                    Case "rel"
                        Dim attrRID As XAttribute = elem.Attributes.FirstOrDefault
                        attrRID.Value = strNewRid
                End Select
            Next elem

            xelemMasters.Add(xelemNewMaster)

            Me.m_xDoc = Nothing
            Me.xDoc = New XDocument
            ' put the updated xElement into the cleared xDocument
            Me.xDoc.Add(xelemMasters)

            ' visual studio get's confused and changes the namespaces
            Dim strEmptyNS As String = " xmlns="""""
            Dim strReplace As String = Me.xDoc.ToString
            strReplace = strReplace.Replace(strEmptyNS, " ")


            byteXML = uniEncoding.GetBytes(strReplace)
            ' overwrite the windows package part with the updated data
            Using memStream As New MemoryStream(bufSize)
                memStream.Write(byteXML, 0, byteXML.Length)
                Me.visPackage.CopyStream(memStream, pkgpartMasters.GetStream())
            End Using ' close the memory stream

            ' add the contents file to the package
            Dim visMaster As clsMaster = New clsMaster
            visMaster.visPackage = Me.visPackage

            ' visual studio get's confused and changes the namespaces
            strReplace = xdocMasterContents.ToString
            strReplace = strReplace.Replace(strEmptyNS, " ")

            visMaster.addMasterToMastersPkgParts(packageCurrent, pkgpartMasters, strNewMasterPath, strNewRid, strReplace)

            visMaster = Nothing
            GC.Collect()


        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
    End Sub


    '
    ' pass in a stencil name/path, master name, and reference to master summary and master contents
    ' update the referenced summary and contents elements
    '
    Public Sub readMasterFromStencil _
        (ByVal strStencilPath As String, _
         ByVal strMasterNameU As String, _
         ByRef xdocMasterSummary As XDocument, _
         ByRef xdocMasterContents As XDocument)

        Dim pkgStencil As clsVisPackage = New clsVisPackage
        Dim lclMasters As clsMasters = New clsMasters
        Dim lclMaster As clsMaster = New clsMaster

        Try

            If File.Exists(strStencilPath) = False Then
                MsgBox(" File " & strStencilPath & " does not exist")
                GoTo ExitHandler
            End If


            pkgStencil.fileCurrent = strStencilPath
            ' build the package part information
            pkgStencil.loadPkgAndParts(Nothing)

            ' go find the masters.xml file and load it
            lclMasters.loadMastersXDoc(pkgStencil)
            ' build the masters dictionary for the stencil
            lclMasters.loadMasters(Nothing)
            ' get the summary data from the masters object for the shape we need
            ' and put it into the master xdoc in the class
            lclMasters.loadMasterSummaryByNameU(strMasterNameU)
            xdocMasterSummary = lclMasters.xDocMaster

            ' now go get the shape contents of the master 
            Dim lclMasterShape As stcMasterData = New stcMasterData

            ' parse out the attributes of the master to get the ID
            lclMasters.visPackage.readAttAndElem(lclMasters.xDocMaster, "", "Master")
            ' get the id from the attributes dictionary
            Dim MasterID As String = lclMasters.visPackage.attDict("ID")
            ' get the master shape info from the masters dictionary using the id as the key
            lclMasterShape = lclMasters.dictMastersID(CLng(MasterID))
            ' load the shape xdoc information
            lclMaster.visPackage = lclMasters.visPackage
            ' read the file and save it locally as an xdocument
            lclMaster.loadMasterShapeXDoc(lclMasterShape.mstFile)
            xdocMasterContents = lclMaster.xDoc

ExitHandler:
        Catch errXml As XmlException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(errXml, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        ' cleanup 
        If pkgStencil IsNot Nothing Then
            pkgStencil = Nothing
        End If
        If lclMasters IsNot Nothing Then
            lclMasters = Nothing
        End If
        If lclMaster IsNot Nothing Then
            lclMaster = Nothing
        End If
        GC.Collect()

    End Sub

#End Region

    '
    '
    '
    Public Sub New()


        Me.m_dictMastersID = Nothing
        Me.dictMastersID = New Dictionary(Of Long, stcMasterData)

        Me.m_visPackage = Nothing
        Me.visPackage = New clsVisPackage

        Me.m_xDoc = Nothing
        Me.xDoc = New XDocument

        Me.m_xDocMaster = Nothing
        Me.xDocMaster = New XDocument

    End Sub

    '
    '
    '
    Protected Overrides Sub Finalize()

        If Me.m_dictMastersID IsNot Nothing Then
            Me.m_dictMastersID = Nothing
        End If

        If Me.m_visPackage IsNot Nothing Then
            Me.m_visPackage = Nothing
        End If

        If Me.m_xDoc IsNot Nothing Then
            Me.m_xDoc = Nothing
        End If

        If Me.m_xDocMaster IsNot Nothing Then
            Me.m_xDocMaster = Nothing
        End If

        MyBase.Finalize()
    End Sub

End Class
